package com.ruoyi.ryzs.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.RyzsHeaderConstants;
import com.ruoyi.common.constant.RyzsUrlConstants;
import com.ruoyi.common.utils.GenerateIpUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.ryzs.domain.BusinessRyzs;
import com.ruoyi.ryzs.domain.RyzsExportDTO;
import com.ruoyi.ryzs.domain.RyzsExportVO;
import com.ruoyi.ryzs.mapper.BusinessRyzsMapper;
import com.ruoyi.ryzs.service.IBusinessRyzsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 人鱼助手Service业务层处理
 *
 * @author nanqiang
 * @date 2022-06-07
 */
@Service
@Slf4j
public class BusinessRyzsServiceImpl extends ServiceImpl<BusinessRyzsMapper, BusinessRyzs> implements IBusinessRyzsService {
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 查询人鱼助手列表
     *
     * @param businessRyzs 人鱼助手
     * @return 人鱼助手
     */
    @Override
    public List<BusinessRyzs> selectBusinessRyzsList(BusinessRyzs businessRyzs) {
        return baseMapper.selectBusinessRyzsList(businessRyzs);
    }

    /**
     * 人鱼助手邀请
     */
    @Override
    public void invitation() {
        for (int i = 0; i < 20; i++) {
            threadPoolTaskExecutor.execute(() -> {
                String randoymIp = GenerateIpUtils.getRandoymIp();
                Map<String, Object> mapInvite = new HashMap<>();
                int accountInfo = (int) ((Math.random() * 9 + 1) * 100000);
                int password = (int) ((Math.random() * 9 + 1) * 100000);
                String account = IdUtils.simpleUUID().substring(0, 2) + accountInfo;
                mapInvite.put("platformId", "6");
                mapInvite.put("productId", "26");
                mapInvite.put("statisticsNo", "787");
                mapInvite.put("username", account);
                mapInvite.put("password", password);
                mapInvite.put("imei", "");
                mapInvite.put("terminal", "web");
                mapInvite.put("referrerUserId", "420858");
                try {
                    HttpResponse response = HttpRequest.post(RyzsUrlConstants.OLD_ACCOUNT_API)
                            .header(RyzsHeaderConstants.CONTENT_TYPE.getKey(), RyzsHeaderConstants.CONTENT_TYPE.getValue())
                            .header(RyzsHeaderConstants.USER_AGENT.getKey(), RyzsHeaderConstants.USER_AGENT.getValue())
                            .header(RyzsHeaderConstants.X_FORWORDED_FOR.getKey(), RyzsHeaderConstants.X_FORWORDED_FOR.setValue(randoymIp))
                            .form(mapInvite)
                            .timeout(5000)
                            .execute();
                    BusinessRyzs businessRyzs = new BusinessRyzs();
                    businessRyzs.setAccount(account);
                    businessRyzs.setPassWord(String.valueOf(password));
                    businessRyzs.setIntegration(Convert.toStr(0));
                    businessRyzs.setUserType(Convert.toStr(0));
                    baseMapper.insert(businessRyzs);
                    log.info("{}", response.body());
                } catch (HttpException e) {
                    log.error("Read timed out! 邀请失败！");
                }
            });
        }
    }

    /**
     * 批量签到获取积分
     */
    @Override
    public Integer batchSignIn() {
        LambdaQueryWrapper<BusinessRyzs> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BusinessRyzs::getDeleted, "0")
                .lt(BusinessRyzs::getSignInTime, DateUtil.beginOfDay(DateUtil.date()))
                .or(wrapper -> wrapper.eq(BusinessRyzs::getDeleted, "0").gt(BusinessRyzs::getSignInTime, DateUtil.endOfDay(DateUtil.date())))
                .or(wrapper -> wrapper.eq(BusinessRyzs::getDeleted, "0").isNull(BusinessRyzs::getSignInTime));
        List<BusinessRyzs> businessRyzsList = baseMapper.selectList(queryWrapper);
        log.info("获取到{}个需要签到的账号", businessRyzsList.size());
        for (BusinessRyzs businessRyzs : businessRyzsList) {
            threadPoolTaskExecutor.execute(() -> {
                String[] loginResult = login(businessRyzs);
                if (null != loginResult) {
                    //签到
                    signIn(loginResult[0]);
                    String integration = getJiFen(loginResult[0]);
                    Integer signInDays = businessRyzs.getSignInDays();
                    businessRyzs.setIntegration(StrUtil.toString(integration));
                    businessRyzs.setUserSelectId(loginResult[1]);
                    businessRyzs.setSignInTime(DateUtil.date());
                    businessRyzs.setSignInDays(ObjectUtil.isNull(signInDays) ? 1 : (signInDays + 1));
                    baseMapper.updateById(businessRyzs);
                }
            });
        }
        return businessRyzsList.size();
    }

    /**
     * 导出固定数量和积分数的账号密码
     * 积分数阶段范围为10阶层内
     */
    @Override
    public void exportQuantity(HttpServletResponse response, RyzsExportDTO exportDTO) {
        Integer exportIntegrationMin = (int) Math.floor(exportDTO.getExportIntegration());
        Integer exportIntegrationMax = exportDTO.getExportIntegration() + 10;
        LambdaQueryWrapper<BusinessRyzs> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BusinessRyzs::getDeleted, "0")
                .ge(BusinessRyzs::getIntegration, exportIntegrationMin)
                .lt(BusinessRyzs::getIntegration, exportIntegrationMax)
                .orderByAsc(BusinessRyzs::getIntegration)
                .last("limit " + exportDTO.getExportQuantity());
        List<BusinessRyzs> businessRyzsList = baseMapper.selectList(queryWrapper);
        if (CollUtil.isEmpty(businessRyzsList)) {
            throw new SecurityException("库存中积分档次在" + exportIntegrationMin + "-" + exportIntegrationMax + "之间的账号数量为空！");
        }
        List<RyzsExportVO> exportVOS = Lists.newArrayList();
        for (BusinessRyzs businessRyzs : businessRyzsList) {
            RyzsExportVO ryzsExportVO = new RyzsExportVO();
            ryzsExportVO.setAccount(businessRyzs.getAccount());
            ryzsExportVO.setPassWord(businessRyzs.getPassWord());
            ryzsExportVO.setIntegration(businessRyzs.getIntegration());
            ryzsExportVO.setAccountPassWord(businessRyzs.getAccount() + "----" + businessRyzs.getPassWord()+ "----" + businessRyzs.getIntegration());
            exportVOS.add(ryzsExportVO);
        }
        //删除导出的账号
        List<Long> ids = businessRyzsList.stream().map(BusinessRyzs::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<BusinessRyzs> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(BusinessRyzs::getId, ids);
        BusinessRyzs businessRyzs = new BusinessRyzs();
        businessRyzs.setRemark("导出删除：" + DateUtil.now() + "，导出数量：" + exportDTO.getExportIntegration() + "，导出批次：" + UUID.fastUUID().toString());
        int update = baseMapper.update(businessRyzs, updateWrapper);
        int i = baseMapper.deleteBatchIds(ids);
        if (update==i && i > 0) {
            log.info("导出删除了{}条数据：{}", i, ids.stream().map(Object::toString).collect(Collectors.joining(",")));
        }
        ExcelUtil<RyzsExportVO> util = new ExcelUtil<RyzsExportVO>(RyzsExportVO.class);
        util.exportExcel(response, exportVOS, "人鱼助手数据");
    }

    /**
     * 登录
     */
    private String[] login(BusinessRyzs businessRyzs) {
        Map<String, Object> map = new HashMap<>();
        map.put("accountNumber", businessRyzs.getAccount());
        map.put("password", businessRyzs.getPassWord());
        map.put("platformId", "6");
        String loginRespStr = HttpRequest.post(RyzsUrlConstants.LOGIN_API)
                .header(RyzsHeaderConstants.CONTENT_TYPE.getKey(), RyzsHeaderConstants.CONTENT_TYPE.getValue())
                .header(RyzsHeaderConstants.X_FORWORDED_FOR.getKey(), RyzsHeaderConstants.X_FORWORDED_FOR.setValue(GenerateIpUtils.getRandoymIp()))
                .form(map)
                .timeout(200000)
                .execute().body();
        JSONObject jsonObject = JSONUtil.toBean(loginRespStr, JSONObject.class);
        if (null != jsonObject.get("content")) {
            String[] str = new String[2];
            JSONObject contentJson = (JSONObject) jsonObject.get("content");
            JSONObject userToken = (JSONObject) contentJson.get("userToken");
            str[0] = String.valueOf(userToken.get("token"));
            str[1] = String.valueOf(userToken.get("userId"));
            log.info("{}", userToken);
            return str;
        } else {
            log.info("登录响应错误，未获取到token:{}", loginRespStr);
            if (loginRespStr.contains("密码错误")) {
                businessRyzs.setDeleted(1);
                businessRyzs.setRemark("密码错误->删除账号！");
                baseMapper.deleteById(businessRyzs);
            }
            return null;
        }
    }

    /**
     * 签到
     */
    private void signIn(String token) {
        String signInResponse = HttpRequest.post(RyzsUrlConstants.SIGNIN_API)
                .header(Header.ACCEPT_CHARSET, "utf-8")
                .header("Authorization", token)
                .header(RyzsHeaderConstants.X_FORWORDED_FOR.getKey(), RyzsHeaderConstants.X_FORWORDED_FOR.setValue(GenerateIpUtils.getRandoymIp()))
                .timeout(200000)
                .execute().body();
        log.info("签到：{}", signInResponse);
    }

    /**
     * 获取积分
     */
    public String getJiFen(String token) {
        Map<String, Object> map = new HashMap<>();
        map.put("platformId", "6");
        map.put("token", token);
        String getJiFenResponse = HttpRequest.get(RyzsUrlConstants.INTEGRAL_API)
                .header(Header.ACCEPT_CHARSET, "utf-8")
                .header("Authorization", token)
                .header(RyzsHeaderConstants.X_FORWORDED_FOR.getKey(), RyzsHeaderConstants.X_FORWORDED_FOR.setValue(GenerateIpUtils.getRandoymIp()))
                .form(map)
                .timeout(200000)
                .execute().body();
        JSONObject jsonObject = JSONUtil.toBean(getJiFenResponse, JSONObject.class);
        JSONObject content = (JSONObject) jsonObject.get("content");
        return String.valueOf(content.get("amount"));
    }
}
